﻿@using CleanArchitecture.Blazor.Server.UI.Components.Fusion
@using ResizeMode = SixLabors.ImageSharp.Processing.ResizeMode
@using Size = SixLabors.ImageSharp.Size
@using Image = SixLabors.ImageSharp.Image
@using SixLabors.ImageSharp.Processing
@using SixLabors.ImageSharp
@using SixLabors.ImageSharp.Formats.Png
@using CleanArchitecture.Blazor.Application.Features.Products.Commands.AddEdit
@using CleanArchitecture.Blazor.Domain.Common.Enums
@using CleanArchitecture.Blazor.Server.UI.Services.JsInterop
@using System.Collections.Immutable

@inject IStringLocalizer<Products> L
@inject IUploadService UploadService

<MudDialog>
    <DialogContent>
        <ActiveUserSession PageComponent="@($"{nameof(ProductFormDialog)}/{_model.Id}")" />
        <MudForm Model="@_model" @ref="@_form" Validation="@(Validator.ValidateValue(_model))">
            <MudGrid Spacing="2">
                <MudItem xs="12">
                    <MudTextField Label="@L["Product Name"]" @bind-Value="_model.Name"
                                  For="@(() => _model.Name)"
                                  Required="true"
                                  RequiredError="@L["product name is required!"]">
                    </MudTextField>
                </MudItem>
                <MudItem xs="12">
                    <MudTextField Label="@L["Description"]"
                                  Lines="3"
                                  For="@(() => _model.Description)"
                                  @bind-Value="_model.Description">
                    </MudTextField>
                </MudItem>
                <MudItem xs="12" sm="4">
                    <PicklistAutocomplete Picklist="Picklist.Brand" T="string"
                                          Label="@L["Brand Name"]"
                                          For="@(() => _model.Brand)"
                                          ResetValueOnEmptyText="true"
                                          ShowProgressIndicator="true"
                                          @bind-Value="_model.Brand">
                        <ProgressIndicatorTemplate>
                            <MudProgressLinear Size="MudBlazor.Size.Small" Indeterminate="true" />
                        </ProgressIndicatorTemplate>
                    </PicklistAutocomplete>
                </MudItem>
                <MudItem xs="12" sm="4">
                    <MudNumericField Label="@L["Price"]"
                                     T="decimal"
                                     Format="N2"
                                     For="@(() => _model.Price)"
                                     Min="0.00m"
                                     @bind-Value="_model.Price">
                    </MudNumericField>
                </MudItem>
                <MudItem xs="12" sm="4">
                    <PicklistAutocomplete Picklist="Picklist.Unit" T="string"
                                          Label="@L["Unit"]"
                                          For="@(() => _model.Unit)"
                                          ResetValueOnEmptyText="true"
                                          ShowProgressIndicator="true"
                                          @bind-Value="_model.Unit">
                        <ProgressIndicatorTemplate>
                            <MudProgressLinear Size="MudBlazor.Size.Small" Indeterminate="true" />
                        </ProgressIndicatorTemplate>
                    </PicklistAutocomplete>
                </MudItem>
                <MudItem xs="12">
                    <MudStack Spacing="1" Class="mb-2">
                        <MudText Typo="Typo.body2">@L["The recommended size for uploading images is 640X320"]</MudText>
                        <MudFileUpload T="IReadOnlyList<IBrowserFile>" multiple
                                       @bind-Files="_model.UploadPictures"
                                       For="@(() => _model.UploadPictures)"
                                       OnFilesChanged="UploadFiles" Accept=".pdf,image/*"
                                       Hidden="@false"
                                       InputClass="absolute mud-width-full mud-height-full overflow-hidden z-100"
                                       InputStyle="opacity:0"
                                       tabindex="-1"
                                       @ondrop="@ClearDragClass"
                                       @ondragenter="@SetDragClass"
                                       @ondragleave="@ClearDragClass"
                                       @ondragend="@ClearDragClass"
                                       AppendMultipleFiles>
                            <ActivatorContent>
                                <MudPaper Class="@_dragClass" Style="width:260px;height:70px;">
                                    <MudLoadingButton Loading="@_uploading" Disabled="@_uploading" Variant="Variant.Text" Class="align-self-center" Style="text-transform:none"
                                                      StartIcon="@Icons.Material.Filled.CloudUpload">
                                        @L["choose image or pdf"]
                                    </MudLoadingButton>
                                </MudPaper>
                            </ActivatorContent>

                        </MudFileUpload>
                        @if (_model.Pictures is not null)
                        {
                            <MudSimpleTable Hover Dense Elevation="0">
                                <tbody>
                                    @foreach (var dto in _model.Pictures)
                                    {
                                        <tr @onclick="()=>OnDownloadFile(dto.Url)" style="cursor:pointer">
                                            <td><Thumbnail FileName="@dto.Name" FileUrl="@dto.Url"> </Thumbnail></td>
                                            <td><FileSizeFormatter FileSizeInBytes="@dto.Size"></FileSizeFormatter></td>
                                            <td style="width:50px"><MudIconButton Icon="@Icons.Material.Outlined.Delete" Color="Color.Error" title="@ConstantString.Delete" OnClick="@(() => DeleteImage(dto))"></MudIconButton></td>
                                        </tr>
                                    }
                                </tbody>
                            </MudSimpleTable>
                        }
                    </MudStack>
                </MudItem>
            </MudGrid>
        </MudForm>

    </DialogContent>
    <DialogActions>
        <MudButton OnClick="Cancel">@ConstantString.Cancel</MudButton>
        <MudLoadingButton Loading="@_saveingnew" OnClick="SaveAndNew">@ConstantString.SaveAndNew</MudLoadingButton>
        <MudLoadingButton Loading="@_saving" OnClick="Submit">@ConstantString.Save</MudLoadingButton>
    </DialogActions>
</MudDialog>

@code {
    [CascadingParameter] private IMudDialogInstance MudDialog { get; set; } = default!;

    [EditorRequired][Parameter] public AddEditProductCommand _model { get; set; } = default!;

    [Parameter] public Action? Refresh { get; set; }

    private MudForm? _form;
    private bool _saving;
    private bool _saveingnew;
    private bool _uploading;

    private const long MaxAllowedSize = 3145728;

    private async Task DeleteImage(ProductImage picture)
    {
        if (_model.Pictures != null)
        {
            var parameters = new DialogParameters<ConfirmationDialog>
            {
                { x => x.ContentText, $"{L["Are you sure you want to erase this image?"]}" }
            };
            var options = new DialogOptions { CloseButton = true, MaxWidth = MaxWidth.ExtraSmall, FullWidth = true };
            var dialog = await DialogService.ShowAsync<ConfirmationDialog>($"{L["Erase imatge"]}", parameters, options);
            var state = await dialog.Result;

            if (state is not null && !state.Canceled)
            {
                _model.Pictures.Remove(picture);
                await UploadService.RemoveAsync(picture.Url);
            }
        }
    }

    private const string DefaultDragClass = "pa-4 d-flex align-content-center align-center flex-grow-1 mb-2 flex-wrap border-2 border-dashed";
    private string _dragClass = DefaultDragClass;
    private void SetDragClass()
        => _dragClass = $"{DefaultDragClass} mud-border-primary mud-elevation-25 border-4";

    private void ClearDragClass()
        => _dragClass = DefaultDragClass;
    private async Task UploadFiles(InputFileChangeEventArgs e)
    {
        try
        {
            ClearDragClass();
            _uploading = true;
            var list = new List<ProductImage>();
            foreach (var file in e.GetMultipleFiles())
            {
                try
                {
                    var filestream = file.OpenReadStream(GlobalVariable.MaxAllowedSize);
                    var attachStream = new MemoryStream();
                    await filestream.CopyToAsync(attachStream);
                    attachStream.Position = 0;
                    var filename = file.Name;
                    var fi = new FileInfo(filename);
                    var ext = fi.Extension;
                    if (ext.EndsWith(".pdf"))
                    {
                        var result = await UploadService.UploadAsync(new UploadRequest(filename, UploadType.Product, attachStream.ToArray()));
                        list.Add(new ProductImage { Name = filename, Size = attachStream.Length, Url = result });
                    }
                    else
                    {
                        var resizedStream = await ImageProcessor.ResizeAndCompressToJpegAsync(attachStream,640,320);
                        var result = await UploadService.UploadAsync(new UploadRequest(filename, UploadType.Product, resizedStream.ToArray(), overwrite: false, null));
                        list.Add(new ProductImage { Name = filename, Size = attachStream.Length, Url = result });
                    }
                }
                catch (Exception ex)
                {
                    Snackbar.Add($"{ex.Message}", Severity.Error);
                }
            }

            Snackbar.Add(L["Upload pictures successfully"], Severity.Info);

            if (_model.Pictures is null)
                _model.Pictures = list;
            else
                _model.Pictures.AddRange(list);
        }
        finally
        {
            _uploading = false;
        }
    }

    private async Task Submit()
    {
        try
        {
            _saving = true;
            await _form!.Validate().ConfigureAwait(false);

            if (!_form!.IsValid)
                return;

   
            var result = await Mediator.Send(_model);
            result.Match(
            data =>
            {
                MudDialog.Close(DialogResult.Ok(true));
                Snackbar.Add(ConstantString.SaveSuccess, Severity.Info);
            },
            errors =>
            {
                Snackbar.Add(errors, Severity.Error);
            });
        }
        finally
        {
            _saving = false;
        }
    }

    private async Task SaveAndNew()
    {
        try
        {
            _saveingnew = true;
            await _form!.Validate().ConfigureAwait(false);
            if (!_form!.IsValid)
                return;
            var result = await Mediator.Send(_model);
            result.Match(
            data =>
            {
                Snackbar.Add(ConstantString.SaveSuccess, Severity.Info);
                Refresh?.Invoke();
                _model = new AddEditProductCommand();
            },
            errors =>
            {
                Snackbar.Add(result.ErrorMessage, Severity.Error);
            });
        }
        finally
        {
            _saveingnew = false;
        }
    }

    private void Cancel()
    {
        MudDialog.Cancel();
    }
    private async Task OnDownloadFile(string? str)
    {
        var fileURL = str;
        await new Fancybox(JS).Preview(str ?? string.Empty, []);
    }
}